package Absyn;
import java.util.Date;
import Symbol.Symbol;


public class Print {

  java.io.PrintStream out;
  public static String str;

  public Print(java.io.PrintStream o) {out=o; str="";}

  void indent(int d) {
	  for(int i=0; i<d; i++){
    	  out.print(' ');
    	  str=str+"  ";
      }
  }

  void say(String s) {
	  out.print(s);
	  str=str+s;
  }

  void say(int i) {
	  Integer local = new Integer(i);
	  out.print(local.toString());
	  str=str+local.toString();
  }

  void say(Date b) {
	  Date local=b;
	  out.print(local.toString());
	  str=str+local.toString();
  }

  void sayln(String s) {
	  say(s); say("\n");
  }

  public void prStmList(StmList e, int d) {
	  indent(d);
	  say("StmList("); 
	  if (e!=null) {
		  sayln("");
		  if(e.statement instanceof SelectExp)
	    	  prExp((SelectExp)e.statement, d+1);
	      else if(e.statement instanceof TabExp)
	    	  prExp((TabExp)e.statement, d+1);
	      else if(e.statement instanceof IndexExp)
	    	  prExp((IndexExp)e.statement, d+1);
	      else if(e.statement instanceof ViewExp)
	    	  prExp((ViewExp)e.statement, d+1);
	      if (e.tail != null) {
	    	  sayln(","); prStmList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prExp(SelectExp e, int d) {
	  	indent(d);
		sayln("SelectExp(");
		prExp((OutputExp)e.outputOption, d+1); sayln(",");
		prAttriList(e.attributes, d+1); sayln(",");
		if(e.source instanceof TabList)
			prTabList((TabList)e.source, d+1);
		else if(e.source instanceof TabOpExp)
			prExp((TabOpExp)e.source, d+1);
		else if(e.source instanceof SelectExp)
			prExp((SelectExp)e.source, d+1);
		else
			throw new Error("Print.prExp.SelectExp");
		if(e.condition!=null){
			sayln(",");
			prExp((MulCondiExp)e.condition, d+1);
		}
		say(")");
  }
  
  void prExp(OutputExp e, int d) {
	indent(d);
	say("OutputExp(");
	switch(e.output_type) {
	    case OutputExp.NONE: 
	    	say("NONE"); break;
	    case OutputExp.DISTINCT: 
	    	say("DISTINCT"); break;
	    case OutputExp.TOP: 
	    	say("TOP "); say(e.top_nr); break;
	    default:
	        throw new Error("Print.prExp.OutputExp");
	}
	say(")");
  }
  
  void prAttriList(AttriList e, int d) {
	  indent(d);
	  say("AttriList(");
	  if (e!=null){
		  if(e.all==1)
			  say("ALL");
		  else {
			  prExp((AttriExp)e.attribute, d+1);
		  }
	      if (e.tail != null) {
	    	  sayln(","); prAttriList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prTabList(TabList e, int d) {
	  indent(d);
	  say("TabList("); 
	  if (e!=null){
		  say(e.table.name);
		  prExp((AsExp)e.name, 1);
	      if (e.tail != null) {
	    	  sayln(","); prTabList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prExp(AsExp e, int d) {
	  	indent(d);
	    say("AsExp(");
	    if(e!=null)
	    	say(e.name.name);
	    else
	    	say("NULL");
	    say(")");
  }
  
  void prExp(TabExp e, int d) {
	   if(e instanceof CreaExp)
		   prExp((CreaExp)e, d);
	   else if(e instanceof AltExp)
		   prExp((AltExp)e, d);
	   else if(e instanceof DelExp)
		   prExp((DelExp)e, d);
	   else if(e instanceof InsertExp)
		   prExp((InsertExp)e, d);
	   else if(e instanceof DropExp)
		   prExp((DropExp)e, d);
	   else if(e instanceof UpdateExp)
		   prExp((UpdateExp)e, d);
	   else
		   throw new Error("Print.prExp.TabExp");
  }
  
  void prExp(AttriExp e, int d) {
	    say("AttriExp(");
	    if(e.table!=null)
	    	say(e.table.name+".");
	    say(e.attribute.name);
	    say(")");
  }
  
  void prExp(IntExp e, int d) {
	    say("IntExp("); say(e.value); say(")");
  }

  void prExp(StrExp e, int d) {
		say("StrExp("); say(e.value); say(")");
  }
  
  void prExp(TabOpExp e, int d) {
	    say("TabOpExp(");
	    switch(e.type) {
	    	case TabOpExp.NATURAL:
		    	say("UNION");
		    	say(e.table1.name+","); say(e.table2.name); prExp((CondiExp)e.condition, d+1);
		    	break;
		    case TabOpExp.INNER:
		    	say("INNER JOIN");
		    	say(e.table1.name+","); say(e.table2.name); prExp((CondiExp)e.condition, d+1);
		    	break;
		    case TabOpExp.CROSS:
		    	say("CROSS JOIN");
		    	say(e.table1.name+","); say(e.table2.name);
		    	break;
		    case TabOpExp.LEFT: 
		    	say("LEFT OUTER JOIN");
		    	say(e.table1.name+","); say(e.table2.name); prExp((CondiExp)e.condition, d+1);
		    	break;
		    case TabOpExp.RIGHT: 
		    	say("RIGHT OUTER JOIN");
		    	say(e.table1.name+","); say(e.table2.name); prExp((CondiExp)e.condition, d+1);
		    	break;
		    case TabOpExp.FULL: 
		    	say("FULL OUTER JOIN");
		    	say(e.table1.name+","); say(e.table2.name); prExp((CondiExp)e.condition, d+1);
		    	break;
		    default:
		      throw new Error("Print.prExp.TabOpExp");
	    }
	    say(")");
  }
  
  void prExp(MulCondiExp e, int d) {
	  if(e!=null) {
		  indent(d);
		  sayln("MulCondiExp(");
		  prExp((IfExp)e.conditions, d+1); sayln(",");
		  if(e.group!=null)
			  prExp((GroupExp)e.group, d+1);
		  else{
			  indent(d+1);
			  say("NULL");
		  }
		  sayln(",");
		  if(e.order!=null)
			  prExp((OrderExp)e.order, d+1);
		  else {
			  indent(d+1);
			  say("NULL");
		  }
		  say(")");
	  }
  }

  void prExp(IfExp e, int d){
	  indent(d);
	  sayln("IfExp(");
	  if(e.test instanceof IfExp)
		  prExp((IfExp)e.test, d+1);
	  else if(e.test instanceof CondiExp)
		  prExp((CondiExp)e.test, d+1);
	  if(e.thenclause instanceof IfExp){
		  sayln(",");
		  prExp((IfExp)e.thenclause, d+1);
	  }
	  else if(e.thenclause instanceof CondiExp){
		  sayln(",");
		  prExp((CondiExp)e.thenclause, d+1);
	  }
	  if (e.elseclause!=null) { /* else is optional */
		  if(e.elseclause instanceof IfExp){
			  sayln(",");
			  prExp((IfExp)e.elseclause, d+1);
		  }
		  else if(e.elseclause instanceof CondiExp){
			  sayln(",");
			  prExp((CondiExp)e.elseclause, d+1);
		  }  
	  }
	  
  }
  
  /*void prCondiList(CondiList e, int d) {
	  if(e.type==CondiList.AND){
		  indent(d-1);
		  sayln(" AND ");
	  }
	  if(e.type==CondiList.OR){
		  indent(d-1);
		  sayln(" OR ");
	  }
	  indent(d);
	  sayln("CondiList(");
	  if (e!=null){
		  prExp((CondiExp)e.condition, d+1);
	      if (e.tail != null) {
	    	  sayln(","); prCondiList(e.tail, d+1);
	      }
	  }
	  say(")");
  }*/
  
  void prExp(CondiExp e, int d) {
	  indent(d);
	  say("CondiExp(");
	  switch(e.type) {
	  	case CondiExp.EXIST: 
	    	say("EXIST"); break;
	    case CondiExp.EQ: 
	    	say("EQ"); break;
	    case CondiExp.NEQ: 
	    	say("NEQ");  break;
	    case CondiExp.LT: 
	    	say("LT");  break;
	    case CondiExp.LE: 
	    	say("LE");  break;
	    case CondiExp.GT: 
	    	say("GT");  break;
	    case CondiExp.GE: 
	    	say("GE");  break;
	    case CondiExp.BETWEEN: 
	    	say("BETWEEN");  break;
	    case CondiExp.IN: 
	    	say("IN");  break;
	    default:
	        throw new Error("Print.prExp.CondiExp");
	  }
	  say(",");
	  if(e.type==CondiExp.EXIST)
		  prExp((SelectExp)e.select, d+1);
	  else if(e.type==CondiExp.EQ || e.type==CondiExp.NEQ ||e.type==CondiExp.LT 
			  ||e.type==CondiExp.LE ||e.type==CondiExp.GT ||e.type==CondiExp.GE){
		  prExp((AttriExp)e.attr1, d+1); say(",");
		  if(e.attr2 instanceof AttriExp)
			  prExp((AttriExp)e.attr2, d+1);
		  else if(e.attr2 instanceof IntExp)
			  prExp((IntExp)e.attr2, d+1);
		  else if(e.attr2 instanceof StrExp)
			  prExp((StrExp)e.attr2, d+1);
		  else
			  throw new Error("Print.prExp.CondiExp2");
	  }
	  else if(e.type==CondiExp.BETWEEN) {
		  prExp((AttriExp)e.attr1, d+1); say(",");
		  prExp((AttriExp)e.attr2, d+1); say(",");
		  prExp((AttriExp)e.attr3, d+1);
	  }
	  else if(e.type==CondiExp.IN){
		  prExp((AttriExp)e.attr1, d+1); say(",");
		  prValList(e.vl, d+1);
	  }
	  else
		  throw new Error("Print.prExp.CondiExp3");
	  say(")");
  }
  
  void prExp(GroupExp e, int d) {
	  say("GroupExp(");
	  prExp((AttriExp)e.attribute,d+1); sayln(",");
	  prExp((AggrExp)e.condition,d+1);
	  say(")");
  }
  
  void prExp(AggrCondiExp e, int d) {
	  say("AggrCondiExp(");
	  switch(e.type){
	    case AggrCondiExp.EQ:
	    	sayln("EQ,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1);
	    	break;
	    case AggrCondiExp.NEQ:
	    	sayln("NEQ,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1);
	    	break;
	    case AggrCondiExp.LT:
	    	sayln("LT,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1);
	    	break;
	    case AggrCondiExp.LE:
	    	sayln("LE,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1);
	    	break;
	    case AggrCondiExp.GT:
	    	sayln("GT,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1);
	    	break;
	    case AggrCondiExp.GE:
	    	sayln("GE,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1);
	    	break;
	    case AggrCondiExp.BETWEEN:
	    	sayln("BETWEEN,"); prExp((AggrExp)e.attribute,d+1); say(","); say(e.value1); say(e.value2);
	    	break;
	    default:
	    	throw new Error("Print.prExp.AggrExp");
	}
  }
  
  void prOrdAttriList(OrdAttriList e, int d){
	  indent(d);
	  say("OrdAttriList(");
	  if (e!=null){
		  prExp((AttriExp)e.attribute, d+1);
		  prExp((IntExp)e.option, d+1);
	      if (e.tail != null) {
	    	  sayln(","); prOrdAttriList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prExp(OrderExp e, int d) {
	  	indent(d);
	    sayln("OrderExp("); 
	    prOrdAttriList(e.attribute, d+1);
	    say(")");
  }
  
  void prExp(AggrExp e, int d) {
	    say("AggrExp(");
	    switch(e.type){
		    case AggrExp.SUM:
		    	sayln("SUM,"); prExp((AttriExp)e.attribute,d+1);
		    	break;
		    case AggrExp.AVG:
		    	sayln("AVG,"); prExp((AttriExp)e.attribute,d+1);
		    	break;
		    case AggrExp.COUNT:
		    	sayln("COUNT,"); prExp((AttriExp)e.attribute,d+1);
		    	break;
		    default:
		    	throw new Error("Print.prExp.AggrExp");
		}
	    say(")");
  }
  
  void prExp(UpdateExp e, int d) {
	  	indent(d);
	    say("UpdateExp(");
	    say(e.table.name); sayln(",");
	    prSetList(e.setList, d+1); sayln(",");
	    if(e.conditions instanceof IfExp)
			  prExp((IfExp)e.conditions, d+1);
		  else if(e.conditions instanceof CondiExp)
			  prExp((CondiExp)e.conditions, d+1);
	    say(")");
  }
  
  void prSetList(SetList e, int d) {
	  indent(d);
	  say("SetList("); 
	  if (e!=null) {
		  prExp((AttriExp)e.attribute, d+1); say(",");
	      if(e.value instanceof IntExp)
	    	  prExp((IntExp)e.value, d+1);
	      else if(e.value instanceof StrExp)
	    	  prExp((StrExp)e.value, d+1);
	      else
	    	  throw new Error("Print.prSetList");
	      if (e.tail != null) {
	    	  sayln(","); prSetList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prExp(DelExp e, int d) {
	    indent(d);
	    say("DelExp(");
	    say(e.table.name); sayln(",");
	    if(e.conditions instanceof IfExp)
			  prExp((IfExp)e.conditions, d+1);
		  else if(e.conditions instanceof CondiExp)
			  prExp((CondiExp)e.conditions, d+1);
	    say(")");
  }
  
  void prExp(InsertExp e, int d) {
	    indent(d);
	    say("InsertExp(");
	    say(e.table.name); sayln(",");
	    prAttriList(e.attributes, d+1); sayln(",");
	    prValList(e.values, d+1);
	    say(")");
  }
  
  void prValList(ValList e, int d) {
	  indent(d);
	  say("ValList("); 
	  if (e!=null) {
	      if(e.value instanceof IntExp)
	    	  prExp((IntExp)e.value, d+1);
	      else if(e.value instanceof StrExp)
	    	  prExp((StrExp)e.value, d+1);
	      else
	    	  throw new Error("Print.prSetList");
	      if (e.tail != null) {
	    	  sayln(","); prValList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prExp(CreaExp e, int d) {
	    indent(d);
	    say("CreaExp(");
	    say(e.table.name); sayln(",");
	    prNewList(e.newList, d+1);
	    say(")");
  }
  
  void prNewList(NewList e, int d) {
	  indent(d);
	  say("NewList("); 
	  if (e!=null) {
	      say(e.attribute.name+",");
	      prTy(e.type, d+1);
	      if (e.tail != null) {
	    	  sayln(","); prNewList(e.tail, d+1);
	      }
	  }
	  say(")");
  }
  
  void prTy(Ty e, int d) {
	    say("TypeExp(");
	    switch(e.type){
	    case Ty.INT:
	    	say("INT,"); say(e.len); break;
	    case Ty.CHAR:
	    	say("CHAR,"); say(e.len); break;
	    case Ty.VARCHAR:
	    	say("VARCHAR,"); say(e.len); break;
	    default:
	    	throw new Error("Print.prTy");
	    }
	    say(")");
  }
  
  void prExp(AltExp e, int d) {
	    indent(d);
	    say("AltExp(");
	    say(e.table.name); say(",");
	    if(e.type==1){
	    	prNewList(e.newlist, d+1);
	    }
	    else {
	    	say(e.delAttri.name);
	    }
	    say(")");
  }
  
  void prExp(DropExp e, int d) {
	    indent(d);
	    say("DropExp(");
	    say(e.table.name);
	    say(")");
  }
  
  void prExp(IndexExp e, int d) {
	   if(e instanceof CreaIndexExp)
		   prExp((CreaIndexExp)e, d);
	   else if(e instanceof DropIndexExp)
		   prExp((DropIndexExp)e, d);
	   else
		   throw new Error("Print.prExp.IndexExp");
  }
  
  void prExp(CreaIndexExp e, int d){
	  	indent(d);
	    say("CreaIndexExp(");
	    say(e.index_name.name);	say(",");
	    say(e.table_name.name); sayln(",");
	    prAttriList(e.attributes, d+1);
	    say(")");
  }
  
  void prExp(DropIndexExp e, int d){
	  	indent(d);
	    say("DropIndexExp(");
	    say(e.index_name.name);	say(",");
	    say(e.table_name.name);
	    say(")");
  }
  
  void prExp(ViewExp e, int d) {
	   if(e instanceof CreaViewExp)
		   prExp((CreaViewExp)e, d);
	   else if(e instanceof DropViewExp)
		   prExp((DropViewExp)e, d);
	   else
		   throw new Error("Print.prExp.ViewExp");
  }
  
  void prExp(CreaViewExp e, int d){
	  	indent(d);
	    say("CreaViewExp(");
	    say(e.view_name.name);	sayln(",");
	    prExp((SelectExp)e.selExp, d+1);
	    say(")");
  }
  
  void prExp(DropViewExp e, int d){
	  	indent(d);
	    say("DropViewExp(");
	    say(e.view_name.name);
	    say(")");
  }
  
}
  

  
  
  
  
  
  
  
  
  
  
  
  
 